package org.jeecg.modules.wms.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.wms.entity.WmsWarehouseLocation;
import org.jeecg.modules.wms.service.IWmsWarehouseLocationService;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

import org.jeecg.modules.wms.entity.WmsWarehouse;
import org.jeecg.modules.wms.service.IWmsWarehouseService;
import org.jeecg.modules.wms.entity.WmsInventory;
import org.jeecg.modules.wms.service.IWmsInventoryService;

/**
 * 库位管理
 */
@Slf4j
@Api(tags = "库位管理")
@RestController
@RequestMapping("/wms/location")
public class WmsWarehouseLocationController extends JeecgController<WmsWarehouseLocation, IWmsWarehouseLocationService> {

    @Autowired
    private IWmsWarehouseLocationService wmsWarehouseLocationService;

    @Autowired
    private IWmsWarehouseService wmsWarehouseService;
    
    @Autowired
    private IWmsInventoryService wmsInventoryService;

    @Value("${jeecg.path.upload}")
    private String upLoadPath;
    /**
     * 分页列表查询
     */
    @AutoLog(value = "库位信息-分页列表查询")
    @ApiOperation(value = "库位信息-分页列表查询", notes = "库位信息-分页列表查询")
    @GetMapping(value = "/list")
    public Result<?> queryPageList(WmsWarehouseLocation wmsWarehouseLocation,
                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                   HttpServletRequest req) {
        QueryWrapper<WmsWarehouseLocation> queryWrapper = QueryGenerator.initQueryWrapper(wmsWarehouseLocation, req.getParameterMap());
        Page<WmsWarehouseLocation> page = new Page<>(pageNo, pageSize);
        IPage<WmsWarehouseLocation> pageList = wmsWarehouseLocationService.getByList(page, queryWrapper);
        return Result.OK(pageList);
    }

    /**
     * 根据仓库ID查询库位列表
     */
    @AutoLog(value = "库位信息-根据仓库ID查询库位列表")
    @ApiOperation(value = "库位信息-根据仓库ID查询库位列表", notes = "库位信息-根据仓库ID查询库位列表")
    @GetMapping(value = "/listByWarehouseId")
    public Result<?> queryListByWarehouseId(@RequestParam(name = "warehouseId", required = true) String warehouseId) {
        List<WmsWarehouseLocation> locationList = wmsWarehouseLocationService.queryLocationListByWarehouseId(warehouseId);
        return Result.OK(locationList);
    }

    /**
     * 添加
     */
    @AutoLog(value = "库位信息-添加")
    @ApiOperation(value = "库位信息-添加", notes = "库位信息-添加")
    @PostMapping(value = "/add")
    public Result<?> add(@RequestBody WmsWarehouseLocation wmsWarehouseLocation) {
        wmsWarehouseLocationService.saveLocation(wmsWarehouseLocation);
        return Result.OK("添加成功！");
    }

    /**
     * 编辑
     */
    @AutoLog(value = "库位信息-编辑")
    @ApiOperation(value = "库位信息-编辑", notes = "库位信息-编辑")
    @PutMapping(value = "/edit")
    public Result<?> edit(@RequestBody WmsWarehouseLocation wmsWarehouseLocation) {
        wmsWarehouseLocationService.updateLocation(wmsWarehouseLocation);
        return Result.OK("编辑成功！");
    }

    /**
     * 通过id删除
     */
    @AutoLog(value = "库位信息-通过id删除")
    @ApiOperation(value = "库位信息-通过id删除", notes = "库位信息-通过id删除")
    @DeleteMapping(value = "/delete")
    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
        wmsWarehouseLocationService.deleteLocation(id);
        return Result.OK("删除成功!");
    }

    /**
     * 批量删除
     */
    @AutoLog(value = "库位信息-批量删除")
    @ApiOperation(value = "库位信息-批量删除", notes = "库位信息-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        wmsWarehouseLocationService.batchDeleteLocation(ids);
        return Result.OK("批量删除成功！");
    }

    /**
     * 通过id查询
     */
    @AutoLog(value = "库位信息-通过id查询")
    @ApiOperation(value = "库位信息-通过id查询", notes = "库位信息-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
        WmsWarehouseLocation wmsWarehouseLocation = wmsWarehouseLocationService.getById(id);
        return Result.OK(wmsWarehouseLocation);
    }

    /**
     * 生成库位二维码
     */
    @AutoLog(value = "库位信息-生成库位二维码")
    @ApiOperation(value = "库位信息-生成库位二维码", notes = "库位信息-生成库位二维码")
    @GetMapping(value = "/generateQrcode")
    public Result<?> generateQrcode(@RequestParam(name = "id", required = true) String id) {
        String qrcodePath = wmsWarehouseLocationService.generateLocationQrcode(id);
        return Result.OK(qrcodePath);
    }

    /**
     * 批量生成库位二维码
     */
    @AutoLog(value = "库位信息-批量生成库位二维码")
    @ApiOperation(value = "库位信息-批量生成库位二维码", notes = "库位信息-批量生成库位二维码")
    @GetMapping(value = "/batchGenerateQrcode")
    public Result<?> batchGenerateQrcode(@RequestParam(name = "warehouseId", required = true) String warehouseId) {
        wmsWarehouseLocationService.batchGenerateLocationQrcode(warehouseId);
        return Result.OK("批量生成二维码成功！");
    }

    /**
     * 批量生成库位
     */
    @AutoLog(value = "库位信息-批量生成库位")
    @ApiOperation(value = "库位信息-批量生成库位", notes = "库位信息-批量生成库位")
    @PostMapping(value = "/batchGenerate")
    public Result<?> batchGenerate(@RequestBody Map<String, Object> params) {
        String warehouseId = (String) params.get("warehouseId");
        String codePrefix = (String) params.get("codePrefix");
        String namePrefix = (String) params.get("namePrefix");
        Integer startNum = Integer.valueOf(params.get("startNum").toString());
        Integer count =  Integer.valueOf(params.get("count").toString());
        Integer numLength = Integer.valueOf(params.get("numLength").toString());
        String status = (String) params.get("status");
        String remark = (String) params.get("remark");

        if (warehouseId == null || "".equals(warehouseId)) {
            return Result.error("仓库ID不能为空");
        }
        if (codePrefix == null || "".equals(codePrefix)) {
            return Result.error("库位编号前缀不能为空");
        }
        if (namePrefix == null || "".equals(namePrefix)) {
            return Result.error("库位名称前缀不能为空");
        }
        if (startNum == null || startNum < 1) {
            return Result.error("起始编号必须大于0");
        }
        if (count == null || count < 1) {
            return Result.error("生成数量必须大于0");
        }
        if (numLength == null || numLength < 1) {
            return Result.error("编号位数必须大于0");
        }

        try {
            int successCount = wmsWarehouseLocationService.batchGenerateLocation(warehouseId, codePrefix, namePrefix, startNum, count, numLength, status, remark);
            return Result.OK("成功生成" + successCount + "个库位");
        } catch (Exception e) {
            log.error("批量生成库位失败", e);
            return Result.error("批量生成库位失败：" + e.getMessage());
        }
    }

    /**
     * 导出excel
     */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, WmsWarehouseLocation wmsWarehouseLocation) {
        // Step.1 组装查询条件
        QueryWrapper<WmsWarehouseLocation> queryWrapper = QueryGenerator.initQueryWrapper(wmsWarehouseLocation, request.getParameterMap());

        // 过滤选中数据
        String selections = request.getParameter("selections");
        if (oConvertUtils.isNotEmpty(selections)) {
            List<String> selectionList = Arrays.asList(selections.split(","));
            queryWrapper.in("id", selectionList);
        }

        // Step.2 获取导出数据
        List<WmsWarehouseLocation> pageList = wmsWarehouseLocationService.queryExportList(wmsWarehouseLocation, request.getParameterMap());

        // 处理数据，确保仓库名称正确导出，移除不需要的字段
        for (WmsWarehouseLocation location : pageList) {
            // 确保库位二维码字段不导出
            location.setLocationQrcode(null);
        }

        // Step.3 AutoPoi 导出Excel
        ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
        // 导出文件名称
        mv.addObject(NormalExcelConstants.FILE_NAME, "库位信息");
        mv.addObject(NormalExcelConstants.CLASS, WmsWarehouseLocation.class);

        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        ExportParams exportParams = new ExportParams("库位信息数据", "导出人:" + user.getRealname(), "库位信息");
        exportParams.setImageBasePath(upLoadPath);
        mv.addObject(NormalExcelConstants.PARAMS, exportParams);
        mv.addObject(NormalExcelConstants.DATA_LIST, pageList);

        return mv;
    }

    /**
     * 通过excel导入数据
     */
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        return super.importExcel(request, response, WmsWarehouseLocation.class);
    }
    /**
     * 根据仓库ID查询库位列表
     */
    @AutoLog(value = "库位管理-根据仓库ID查询库位列表")
    @ApiOperation(value = "库位管理-根据仓库ID查询库位列表", notes = "库位管理-根据仓库ID查询库位列表")
    @GetMapping(value = "/queryByWarehouseId")
    public Result<List<WmsWarehouseLocation>> queryByWarehouseId(@RequestParam(name = "warehouseId", required = true) String warehouseId) {
        List<WmsWarehouseLocation> locationList = wmsWarehouseLocationService.queryLocationListByWarehouseId(warehouseId);
        return Result.OK(locationList);
    }
    
    /**
     * 查询空库位
     */
    @AutoLog(value = "库位管理-查询空库位")
    @ApiOperation(value = "库位管理-查询空库位", notes = "库位管理-查询空库位")
    @GetMapping(value = "/queryEmptyLocations")
    public Result<List<WmsWarehouseLocation>> queryEmptyLocations(@RequestParam(name = "warehouseId", required = true) String warehouseId) {
        log.info("查询空库位, warehouseId: {}", warehouseId);
        
        try {
            // 调用服务查询空库位
            List<WmsWarehouseLocation> emptyLocations = wmsWarehouseLocationService.queryEmptyLocations(warehouseId);
            return Result.OK(emptyLocations);
        } catch (Exception e) {
            log.error("查询空库位失败", e);
            return Result.error("查询空库位失败: " + e.getMessage());
        }
    }
    
    /**
     * 根据仓库ID和仓库类型查询库位
     */
    @AutoLog(value = "库位管理-根据仓库ID和仓库类型查询库位")
    @ApiOperation(value = "库位管理-根据仓库ID和仓库类型查询库位", notes = "库位管理-根据仓库ID和仓库类型查询库位")
    @GetMapping(value = "/queryByWarehouseAndType")
    public Result<IPage<WmsWarehouseLocation>> queryByWarehouseAndType(
            @RequestParam(name = "warehouseId", required = true) String warehouseId,
            @RequestParam(name = "warehouseType", required = true) String warehouseType,
            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
        log.info("根据仓库ID和仓库类型查询库位, warehouseId: {}, warehouseType: {}", warehouseId, warehouseType);
        
        try {
            Page<WmsWarehouseLocation> page = new Page<>(pageNo, pageSize);
            
            // 构建查询条件
            LambdaQueryWrapper<WmsWarehouseLocation> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(WmsWarehouseLocation::getWarehouseId, warehouseId);
            queryWrapper.eq(WmsWarehouseLocation::getStatus, "1"); // 只查询可用的库位
            
            // 执行查询
            IPage<WmsWarehouseLocation> pageList = wmsWarehouseLocationService.page(page, queryWrapper);
            
            return Result.OK(pageList);
        } catch (Exception e) {
            log.error("查询库位失败", e);
            return Result.error("查询库位失败: " + e.getMessage());
        }
    }

    /**
     * 根据仓库ID和物料类型查询可用库位
     */
    @AutoLog(value = "库位管理-根据仓库ID和物料类型查询可用库位")
    @ApiOperation(value = "库位管理-根据仓库ID和物料类型查询可用库位", notes = "库位管理-根据仓库ID和物料类型查询可用库位")
    @GetMapping(value = "/queryAvailableLocations")
    public Result<List<WmsWarehouseLocation>> queryAvailableLocations(
            @RequestParam(name = "warehouseId", required = true) String warehouseId,
            @RequestParam(name = "materialType", required = true) String materialType) {
        log.info("根据仓库ID和物料类型查询可用库位, warehouseId: {}, materialType: {}", warehouseId, materialType);
        
        try {
            // 查询仓库信息，确认仓库类型是否匹配物料类型
            WmsWarehouse warehouse = wmsWarehouseService.getById(warehouseId);
            if (warehouse == null) {
                return Result.error("仓库不存在");
            }
            
            // 获取仓库类型
            String warehouseType = warehouse.getWarehouseType();
            
            // 检查仓库类型是否支持该物料类型
            boolean isSupported = false;
            
            // 严格按照仓库类型和物料类型一一对应
            switch (warehouseType) {
                case "1": // 型材库(1)只能存放型材(1)
                    isSupported = "1".equals(materialType);
                    break;
                case "2": // 配件库(2)只能存放配件(2)
                    isSupported = "2".equals(materialType);
                    break;
                case "3": // 辅件库(3)只能存放辅件(3)
                    isSupported = "3".equals(materialType);
                    break;
                case "4": // 其他库(4)只能存放其他物料(4)
                    isSupported = "4".equals(materialType);
                    break;
                case "5": // 余料库(5)只能存放余料(5)
                    isSupported = "5".equals(materialType);
                    break;
                case "6": // 半料库(6)只能存放半料(6)
                    isSupported = "6".equals(materialType);
                    break;
                case "7": // 成品库(7)暂不使用
                case "8": // 半成品库(8)暂不使用
                    return Result.error("该仓库类型暂不使用");
                case "0": // 通用仓库暂不使用
                    return Result.error("通用仓库暂不使用");
                default:
                    return Result.error("未知的仓库类型");
            }
            
            if (!isSupported) {
                return Result.error("该仓库不支持存放此类型物料");
            }
            
            // 查询可用库位（状态为0-空闲或1-占用但未满的库位）
            List<WmsWarehouseLocation> availableLocations = wmsWarehouseLocationService.queryAvailableLocations(warehouseId);
            return Result.OK(availableLocations);
        } catch (Exception e) {
            log.error("查询可用库位失败", e);
            return Result.error("查询可用库位失败: " + e.getMessage());
        }
    }

    /**
     * 根据仓库ID列表和物料列表查询可用库位
     */
    @AutoLog(value = "库位管理-根据仓库ID列表和物料列表查询可用库位")
    @ApiOperation(value = "库位管理-根据仓库ID列表和物料列表查询可用库位", notes = "库位管理-根据仓库ID列表和物料列表查询可用库位")
    @PostMapping(value = "/queryAvailableLocationsByMaterials")
    public Result<?> queryAvailableLocationsByMaterials(@RequestBody Map<String, Object> params) {
        log.info("根据仓库ID列表和物料列表查询可用库位, params: {}", params);
        
        try {
            // 获取参数
            @SuppressWarnings("unchecked")
            List<String> warehouseIds = (List<String>) params.get("warehouseIds");
            @SuppressWarnings("unchecked")
            List<Map<String, Object>> materials = (List<Map<String, Object>>) params.get("materials");
            
            if (warehouseIds == null || warehouseIds.isEmpty()) {
                return Result.error("仓库ID列表不能为空");
            }
            
            if (materials == null || materials.isEmpty()) {
                return Result.error("物料列表不能为空");
            }
            
            // 为每个物料分配库位
            List<Map<String, Object>> result = new ArrayList<>();
            
            for (Map<String, Object> material : materials) {
                String materialId = (String) material.get("id");
                String materialCode = (String) material.get("materialCode");
                String materialType = (String) material.get("materialType");
                
                // 查找适合该物料类型的仓库
                String selectedWarehouseId = null;
                WmsWarehouse selectedWarehouse = null;
                
                for (String warehouseId : warehouseIds) {
                    WmsWarehouse warehouse = wmsWarehouseService.getById(warehouseId);
                    if (warehouse == null) continue;
                    
                    String warehouseType = warehouse.getWarehouseType();
                    boolean isSupported = false;
                    
                    // 严格按照仓库类型和物料类型一一对应
                    switch (warehouseType) {
                        case "1": // 型材库(1)只能存放型材(1)
                            isSupported = "1".equals(materialType);
                            break;
                        case "2": // 配件库(2)只能存放配件(2)
                            isSupported = "2".equals(materialType);
                            break;
                        case "3": // 辅件库(3)只能存放辅件(3)
                            isSupported = "3".equals(materialType);
                            break;
                        case "4": // 其他库(4)只能存放其他物料(4)
                            isSupported = "4".equals(materialType);
                            break;
                        case "5": // 余料库(5)只能存放余料(5)
                            isSupported = "5".equals(materialType);
                            break;
                        case "6": // 半料库(6)只能存放半料(6)
                            isSupported = "6".equals(materialType);
                            break;
                    }
                    
                    if (isSupported) {
                        selectedWarehouseId = warehouseId;
                        selectedWarehouse = warehouse;
                        break;
                    }
                }
                
                if (selectedWarehouseId == null) {
                    // 没有找到适合的仓库，记录错误信息
                    Map<String, Object> errorResult = new HashMap<>();
                    errorResult.put("materialId", materialId);
                    errorResult.put("materialCode", materialCode);
                    errorResult.put("error", "没有找到适合该物料类型的仓库");
                    errorResult.put("success", false);
                    result.add(errorResult);
                    continue;
                }
                
                // 在选中的仓库中查询可用库位
                // 先查询未满的库位(状态为1)
                List<WmsWarehouseLocation> partiallyOccupiedLocations = wmsWarehouseLocationService.queryPartiallyOccupiedLocations(selectedWarehouseId, materialCode);
                
                // 如果没有未满的库位，再查询空闲的库位(状态为0)
                List<WmsWarehouseLocation> availableLocations;
                if (partiallyOccupiedLocations != null && !partiallyOccupiedLocations.isEmpty()) {
                    availableLocations = partiallyOccupiedLocations;
                } else {
                    availableLocations = wmsWarehouseLocationService.queryEmptyLocations(selectedWarehouseId);
                }
                
                if (availableLocations == null || availableLocations.isEmpty()) {
                    // 没有找到可用库位，记录错误信息
                    Map<String, Object> errorResult = new HashMap<>();
                    errorResult.put("materialId", materialId);
                    errorResult.put("materialCode", materialCode);
                    errorResult.put("error", "在仓库" + selectedWarehouse.getWarehouseName() + "中没有找到可用库位");
                    errorResult.put("success", false);
                    result.add(errorResult);
                    continue;
                }
                
                // 选择第一个可用库位
                WmsWarehouseLocation selectedLocation = availableLocations.get(0);
                
                // 记录分配结果
                Map<String, Object> successResult = new HashMap<>();
                successResult.put("materialId", materialId);
                successResult.put("materialCode", materialCode);
                successResult.put("warehouseId", selectedWarehouseId);
                successResult.put("warehouseName", selectedWarehouse.getWarehouseName());
                successResult.put("locationId", selectedLocation.getId());
                successResult.put("locationName", selectedLocation.getLocationName());
                successResult.put("success", true);
                result.add(successResult);
            }
            
            return Result.OK(result);
        } catch (Exception e) {
            log.error("查询可用库位失败", e);
            return Result.error("查询可用库位失败: " + e.getMessage());
        }
    }

    /**
     * 根据物料类型推荐库位
     * 返回推荐的仓库和库位信息，前端可以根据需要修改分配结果
     */
    @AutoLog(value = "库位管理-根据物料类型推荐库位")
    @ApiOperation(value = "库位管理-根据物料类型推荐库位", notes = "库位管理-根据物料类型推荐库位")
    @PostMapping(value = "/recommendLocationsByMaterialTypes")
    public Result<?> recommendLocationsByMaterialTypes(@RequestBody Map<String, Object> params) {
        log.info("根据物料类型推荐库位, params: {}", params);
        
        try {
            // 获取参数
            @SuppressWarnings("unchecked")
            List<Map<String, Object>> materials = (List<Map<String, Object>>) params.get("materials");
            
            if (materials == null || materials.isEmpty()) {
                return Result.error("物料列表不能为空");
            }
            
            // 获取所有仓库列表，供前端选择
            List<WmsWarehouse> allWarehouses = wmsWarehouseService.list();
            
            // 获取所有未完成入库单中已分配的库位信息
            Map<String, String> pendingLocations = wmsWarehouseLocationService.getPendingAllocatedLocations();
            log.info("获取到未入库但已分配的库位数量: {}", pendingLocations.size());
            
            // 为每个物料分配库位
            List<Map<String, Object>> result = new ArrayList<>();
            
            // 记录已分配的库位ID，避免多个物料分配到同一个库位
            Map<String, String> assignedLocations = new HashMap<>();
            // 合并当前会话中分配的库位和系统中未入库但已分配的库位
            assignedLocations.putAll(pendingLocations);
            
            for (Map<String, Object> material : materials) {
                String materialId = (String) material.get("id");
                String materialCode = (String) material.get("materialCode");
                String materialType = String.valueOf(material.get("materialType"));
                
                // 根据物料类型查找适合的仓库
                WmsWarehouse selectedWarehouse = null;
                
                // 根据物料类型查询适合的仓库
                try {
                    selectedWarehouse = wmsWarehouseService.getRecommendedWarehouse(materialType);
                } catch (Exception e) {
                    log.error("查询推荐仓库失败", e);
                }
                
                if (selectedWarehouse == null) {
                    // 没有找到适合的仓库，记录错误信息
                    Map<String, Object> errorResult = new HashMap<>();
                    errorResult.put("materialId", materialId);
                    errorResult.put("materialCode", materialCode);
                    errorResult.put("error", "没有找到适合该物料类型的仓库");
                    errorResult.put("success", false);
                    
                    // 添加所有仓库列表，供前端选择
                    List<Map<String, Object>> warehousesList = new ArrayList<>();
                    for (WmsWarehouse warehouse : allWarehouses) {
                        Map<String, Object> warehouseInfo = new HashMap<>();
                        warehouseInfo.put("id", warehouse.getId());
                        warehouseInfo.put("warehouseName", warehouse.getWarehouseName());
                        warehouseInfo.put("warehouseType", warehouse.getWarehouseType());
                        warehousesList.add(warehouseInfo);
                    }
                    errorResult.put("allWarehouses", warehousesList);
                    
                    result.add(errorResult);
                    continue;
                }
                
                String selectedWarehouseId = selectedWarehouse.getId();
                
                // 在选中的仓库中查询可用库位
                // 先查询未满的库位(状态为1)
                List<WmsWarehouseLocation> partiallyOccupiedLocations = wmsWarehouseLocationService.queryPartiallyOccupiedLocations(selectedWarehouseId, materialCode);
                
                // 如果没有未满的库位，再查询空闲的库位(状态为0)
                List<WmsWarehouseLocation> availableLocations;
                if (partiallyOccupiedLocations != null && !partiallyOccupiedLocations.isEmpty()) {
                    availableLocations = partiallyOccupiedLocations;
                } else {
                    availableLocations = wmsWarehouseLocationService.queryEmptyLocations(selectedWarehouseId);
                }
                
                if (availableLocations == null || availableLocations.isEmpty()) {
                    // 没有找到可用库位，记录错误信息
                    Map<String, Object> errorResult = new HashMap<>();
                    errorResult.put("materialId", materialId);
                    errorResult.put("materialCode", materialCode);
                    errorResult.put("error", "在仓库" + selectedWarehouse.getWarehouseName() + "中没有找到可用库位");
                    errorResult.put("success", false);
                    
                    // 添加所有仓库列表，供前端选择
                    List<Map<String, Object>> warehousesList = new ArrayList<>();
                    for (WmsWarehouse warehouse : allWarehouses) {
                        Map<String, Object> warehouseInfo = new HashMap<>();
                        warehouseInfo.put("id", warehouse.getId());
                        warehouseInfo.put("warehouseName", warehouse.getWarehouseName());
                        warehouseInfo.put("warehouseType", warehouse.getWarehouseType());
                        warehousesList.add(warehouseInfo);
                    }
                    errorResult.put("allWarehouses", warehousesList);
                    
                    result.add(errorResult);
                    continue;
                }
                
                // 选择一个未分配的可用库位
                WmsWarehouseLocation selectedLocation = null;
                for (WmsWarehouseLocation location : availableLocations) {
                    // 检查库位是否已被当前会话分配或者被其他未完成入库单分配
                    if (!assignedLocations.containsKey(location.getId())) {
                        selectedLocation = location;
                        // 记录该库位已被分配
                        assignedLocations.put(location.getId(), materialCode);
                        break;
                    } else {
                        log.debug("库位[{}]已被分配给物料[{}]，跳过", location.getId(), assignedLocations.get(location.getId()));
                    }
                }
                
                // 如果所有库位都已分配，提示错误
                if (selectedLocation == null) {
                    Map<String, Object> errorResult = new HashMap<>();
                    errorResult.put("materialId", materialId);
                    errorResult.put("materialCode", materialCode);
                    errorResult.put("error", "在仓库" + selectedWarehouse.getWarehouseName() + "中所有可用库位已被分配，请增加库位");
                    errorResult.put("success", false);
                    
                    // 添加所有仓库列表，供前端选择
                    List<Map<String, Object>> warehousesList = new ArrayList<>();
                    for (WmsWarehouse warehouse : allWarehouses) {
                        Map<String, Object> warehouseInfo = new HashMap<>();
                        warehouseInfo.put("id", warehouse.getId());
                        warehouseInfo.put("warehouseName", warehouse.getWarehouseName());
                        warehouseInfo.put("warehouseType", warehouse.getWarehouseType());
                        warehousesList.add(warehouseInfo);
                    }
                    errorResult.put("allWarehouses", warehousesList);
                    
                    result.add(errorResult);
                    continue;
                }
                
                // 记录分配结果，返回更完整的仓库和库位信息
                Map<String, Object> successResult = new HashMap<>();
                successResult.put("materialId", materialId);
                successResult.put("materialCode", materialCode);
                successResult.put("warehouseId", selectedWarehouseId);
                successResult.put("warehouseName", selectedWarehouse.getWarehouseName());
                successResult.put("warehouseType", selectedWarehouse.getWarehouseType());
                successResult.put("locationId", selectedLocation.getId());
                successResult.put("locationName", selectedLocation.getLocationName());
                successResult.put("locationCode", selectedLocation.getLocationCode());
                successResult.put("locationStatus", selectedLocation.getStatus());
                successResult.put("success", true);
                
                // 添加可用库位列表，方便前端选择
                List<Map<String, Object>> availableLocationsList = new ArrayList<>();
                for (WmsWarehouseLocation location : availableLocations) {
                    Map<String, Object> locationInfo = new HashMap<>();
                    locationInfo.put("id", location.getId());
                    locationInfo.put("locationName", location.getLocationName());
                    locationInfo.put("locationCode", location.getLocationCode());
                    locationInfo.put("status", location.getStatus());
                    // 标记是否已被分配（当前会话或其他未完成入库单）
                    boolean isAssigned = assignedLocations.containsKey(location.getId());
                    locationInfo.put("assigned", isAssigned);
                    if (isAssigned && pendingLocations.containsKey(location.getId())) {
                        locationInfo.put("pendingAssigned", true);
                        locationInfo.put("assignedTo", pendingLocations.get(location.getId()));
                    }
                    availableLocationsList.add(locationInfo);
                }
                successResult.put("availableLocations", availableLocationsList);
                
                // 添加所有仓库列表，供前端选择
                List<Map<String, Object>> warehousesList = new ArrayList<>();
                for (WmsWarehouse warehouse : allWarehouses) {
                    Map<String, Object> warehouseInfo = new HashMap<>();
                    warehouseInfo.put("id", warehouse.getId());
                    warehouseInfo.put("warehouseName", warehouse.getWarehouseName());
                    warehouseInfo.put("warehouseType", warehouse.getWarehouseType());
                    warehousesList.add(warehouseInfo);
                }
                successResult.put("allWarehouses", warehousesList);
                
                result.add(successResult);
            }
            
            return Result.OK(result);
        } catch (Exception e) {
            log.error("推荐库位失败", e);
            return Result.error("推荐库位失败: " + e.getMessage());
        }
    }

    /**
     * 根据成品订单明细推荐库位
     * 为成品入库分配库位，基于订单编号+窗号进行分配
     */
    @AutoLog(value = "库位管理-根据成品订单明细推荐库位")
    @ApiOperation(value = "库位管理-根据成品订单明细推荐库位", notes = "库位管理-根据成品订单明细推荐库位")
    @PostMapping(value = "/recommendLocationsByFinishedGoods")
    public Result<?> recommendLocationsByFinishedGoods(@RequestBody Map<String, Object> params) {
        log.info("根据成品订单明细推荐库位, params: {}", params);
        
        try {
            // 获取参数
            @SuppressWarnings("unchecked")
            List<Map<String, Object>> finishedGoods = (List<Map<String, Object>>) params.get("finishedGoods");
            String orderNo = (String) params.get("orderNo");
            
            if (finishedGoods == null || finishedGoods.isEmpty()) {
                return Result.error("成品明细列表不能为空");
            }
            
            if (orderNo == null || orderNo.trim().isEmpty()) {
                return Result.error("订单编号不能为空");
            }
            
            // 获取成品仓库(type=7)
            List<WmsWarehouse> finishedGoodsWarehouses = wmsWarehouseService.list(
                new QueryWrapper<WmsWarehouse>().eq("warehouse_type", "7")
            );
            
            if (finishedGoodsWarehouses.isEmpty()) {
                return Result.error("未找到成品仓库，请先配置type=7的仓库");
            }
            
            // 选择第一个成品仓库
            WmsWarehouse selectedWarehouse = finishedGoodsWarehouses.get(0);
            String selectedWarehouseId = selectedWarehouse.getId();
            
            // 获取所有未完成入库单中已分配的库位信息
            Map<String, String> pendingLocations = wmsWarehouseLocationService.getPendingAllocatedLocations();
            log.info("获取到未入库但已分配的库位数量: {}", pendingLocations.size());
            
            // 为每个成品明细分配库位
            List<Map<String, Object>> result = new ArrayList<>();
            
            // 记录已分配的库位ID，避免多个成品分配到同一个库位
            Map<String, String> assignedLocations = new HashMap<>();
            // 合并当前会话中分配的库位和系统中未入库但已分配的库位
            assignedLocations.putAll(pendingLocations);
            
            for (Map<String, Object> finishedGood : finishedGoods) {
                String orderDetailId = (String) finishedGood.get("orderDetailId");
                String windowNo = (String) finishedGood.get("windowNo");
                String windowSeries = (String) finishedGood.get("windowSeries");
                
                // 构建成品标识：订单编号+窗号
                String finishedGoodKey = orderNo + "-" + (windowNo != null ? windowNo : "");
                
                // 在成品仓库中查询可用库位
                // 先查询未满的库位(状态为1)，按库位编码排序
                List<WmsWarehouseLocation> partiallyOccupiedLocations = wmsWarehouseLocationService.queryPartiallyOccupiedLocations(selectedWarehouseId, finishedGoodKey);
                
                // 如果没有未满的库位，再查询空闲的库位(状态为0)
                List<WmsWarehouseLocation> availableLocations;
                if (partiallyOccupiedLocations != null && !partiallyOccupiedLocations.isEmpty()) {
                    availableLocations = partiallyOccupiedLocations;
                } else {
                    availableLocations = wmsWarehouseLocationService.queryEmptyLocations(selectedWarehouseId);
                }
                
                if (availableLocations == null || availableLocations.isEmpty()) {
                    // 没有找到可用库位，记录错误信息
                    Map<String, Object> errorResult = new HashMap<>();
                    errorResult.put("orderDetailId", orderDetailId);
                    errorResult.put("windowNo", windowNo);
                    errorResult.put("error", "在成品仓库" + selectedWarehouse.getWarehouseName() + "中没有找到可用库位");
                    errorResult.put("success", false);
                    
                    result.add(errorResult);
                    continue;
                }
                
                // 选择一个未分配的可用库位
                WmsWarehouseLocation selectedLocation = null;
                for (WmsWarehouseLocation location : availableLocations) {
                    // 检查库位是否已被当前会话分配或者被其他未完成入库单分配
                    if (!assignedLocations.containsKey(location.getId())) {
                        selectedLocation = location;
                        // 记录该库位已被分配
                        assignedLocations.put(location.getId(), finishedGoodKey);
                        break;
                    } else {
                        log.debug("库位[{}]已被分配给成品[{}]，跳过", location.getId(), assignedLocations.get(location.getId()));
                    }
                }
                
                // 如果所有库位都已分配，提示错误
                if (selectedLocation == null) {
                    Map<String, Object> errorResult = new HashMap<>();
                    errorResult.put("orderDetailId", orderDetailId);
                    errorResult.put("windowNo", windowNo);
                    errorResult.put("error", "在成品仓库" + selectedWarehouse.getWarehouseName() + "中所有可用库位已被分配，请增加库位");
                    errorResult.put("success", false);
                    
                    result.add(errorResult);
                    continue;
                }
                
                // 记录分配结果，返回更完整的仓库和库位信息
                Map<String, Object> successResult = new HashMap<>();
                successResult.put("orderDetailId", orderDetailId);
                successResult.put("windowNo", windowNo);
                successResult.put("windowSeries", windowSeries);
                successResult.put("warehouseId", selectedWarehouseId);
                successResult.put("warehouseName", selectedWarehouse.getWarehouseName());
                successResult.put("warehouseType", selectedWarehouse.getWarehouseType());
                successResult.put("locationId", selectedLocation.getId());
                successResult.put("locationName", selectedLocation.getLocationName());
                successResult.put("locationCode", selectedLocation.getLocationCode());
                successResult.put("locationStatus", selectedLocation.getStatus());
                successResult.put("success", true);
                
                result.add(successResult);
            }
            
            return Result.OK(result);
        } catch (Exception e) {
            log.error("推荐成品库位失败", e);
            return Result.error("推荐成品库位失败: " + e.getMessage());
        }
    }
    
    /**
     * 查询调拨入库目标仓库可用库位
     * 只返回状态为1空闲或2占用（同一物料编号）的库位
     */
    @AutoLog(value = "库位管理-查询调拨入库目标仓库可用库位")
    @ApiOperation(value = "库位管理-查询调拨入库目标仓库可用库位", notes = "库位管理-查询调拨入库目标仓库可用库位")
    @GetMapping(value = "/queryAvailableLocationsForTransfer")
    public Result<List<WmsWarehouseLocation>> queryAvailableLocationsForTransfer(
            @RequestParam(name = "warehouseId", required = true) String warehouseId,
            @RequestParam(name = "materialCode", required = true) String materialCode) {
        log.info("查询调拨入库目标仓库可用库位, warehouseId: {}, materialCode: {}", warehouseId, materialCode);
        
        try {
            // 查询仓库信息，确认仓库存在
            WmsWarehouse warehouse = wmsWarehouseService.getById(warehouseId);
            if (warehouse == null) {
                return Result.error("仓库不存在");
            }
            
            // 查询可用库位列表
            List<WmsWarehouseLocation> availableLocations = new ArrayList<>();
            
            // 1. 首先查询状态为1(空闲)的库位
            LambdaQueryWrapper<WmsWarehouseLocation> emptyLocationQuery = new LambdaQueryWrapper<>();
            emptyLocationQuery.eq(WmsWarehouseLocation::getWarehouseId, warehouseId);
            emptyLocationQuery.eq(WmsWarehouseLocation::getStatus, "1"); // 1-空闲
            List<WmsWarehouseLocation> emptyLocations = wmsWarehouseLocationService.list(emptyLocationQuery);
            
            if (emptyLocations != null && !emptyLocations.isEmpty()) {
                availableLocations.addAll(emptyLocations);
            }
            
            // 2. 查询状态为2(占用)且存放相同物料编码的库位
            // 先查询当前物料在目标仓库中的库存记录
            LambdaQueryWrapper<WmsInventory> inventoryQuery = new LambdaQueryWrapper<>();
            inventoryQuery.eq(WmsInventory::getWarehouseId, warehouseId);
            inventoryQuery.eq(WmsInventory::getMaterialCode, materialCode);
            List<WmsInventory> inventoryList = wmsInventoryService.list(inventoryQuery);
            
            // 获取这些库存记录对应的库位ID
            if (inventoryList != null && !inventoryList.isEmpty()) {
                List<String> locationIds = new ArrayList<>();
                for (WmsInventory inventory : inventoryList) {
                    if (inventory.getLocationId() != null) {
                        locationIds.add(inventory.getLocationId());
                    }
                }
                
                if (!locationIds.isEmpty()) {
                    // 查询这些库位信息
                    LambdaQueryWrapper<WmsWarehouseLocation> occupiedLocationQuery = new LambdaQueryWrapper<>();
                    occupiedLocationQuery.in(WmsWarehouseLocation::getId, locationIds);
                    occupiedLocationQuery.eq(WmsWarehouseLocation::getStatus, "2"); // 2-占用
                    List<WmsWarehouseLocation> occupiedLocations = wmsWarehouseLocationService.list(occupiedLocationQuery);
                    
                    if (occupiedLocations != null && !occupiedLocations.isEmpty()) {
                        availableLocations.addAll(occupiedLocations);
                    }
                }
            }
            //availableLocations根据status倒叙排序
            availableLocations.sort(Comparator.comparing(WmsWarehouseLocation::getStatus).reversed());
            
            return Result.OK(availableLocations);
        } catch (Exception e) {
            log.error("查询调拨入库目标仓库可用库位失败", e);
            return Result.error("查询调拨入库目标仓库可用库位失败: " + e.getMessage());
        }
    }
}